<template>
  <div class="excel-importer">
    <el-upload
      :action="action"
      :auto-upload="false"
      :on-change="handleFileChange"
      :show-file-list="showFileList"
      :accept="accept"
      :limit="1"
      :multiple="false"
    >
      <template #trigger>
        <slot name="trigger">
          <el-button type="primary">选择文件</el-button>
        </slot>
      </template>
      <!-- <template #tip>
        <slot name="tip">
          <div class="el-upload__tip">请上传Excel文件 (.xlsx, .xls)</div>
        </slot>
      </template> -->
    </el-upload>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import * as XLSX from 'xlsx'

// 定义props
interface Props {
  // 上传地址（实际不使用，因为本地处理）
  action?: string
  // 是否显示文件列表
  showFileList?: boolean
  // 接受的文件类型
  accept?: string
  // 列映射关系 { excel列名: 对象属性名 }
  columnMap?: Record<string, string>
  // 验证规则 { 对象属性名: 正则表达式 }
  validationRules?: Record<string, { pattern: RegExp; message: string }>
}

const props = withDefaults(defineProps<Props>(), {
  action: '#',
  showFileList: false,
  accept: '.xlsx,.xls',
  columnMap: () => ({}),
  validationRules: () => ({}),
})

// 定义事件
const emit = defineEmits(['import-success', 'import-error', 'validation-error'])

// 处理文件变化
const handleFileChange = async (file: File) => {
  if (!file) return

  try {
    const data = await readExcel(file)
    const { result, errors } = validateData(data)

    if (errors.length > 0) {
      emit('validation-error', errors)
    } else {
      emit('import-success', result)
    }
  } catch (error) {
    console.error('Excel导入错误:', error)
    emit('import-error', error)
  }
}

// 读取Excel文件
const readExcel = (file: File): Promise<any[]> => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()

    reader.onload = (e: ProgressEvent<FileReader>) => {
      try {
        const data = e.target?.result
        const workbook = XLSX.read(data, { type: 'binary' })
        const firstSheetName = workbook.SheetNames[0]
        const worksheet = workbook.Sheets[firstSheetName]

        // 将Excel数据转换为JSON
        let json = XLSX.utils.sheet_to_json(worksheet, { header: 'A' })

        // 如果有表头行，使用表头作为键
        if (json.length > 0) {
          const headers = json[0]
          json = json.slice(1).map((row: any) => {
            const item: Record<string, any> = {}

            // 使用列映射关系转换属性名
            Object.keys(row).forEach((key) => {
              const headerValue = headers[key]
              const mappedKey = props.columnMap[headerValue] || headerValue
              item[mappedKey] = row[key]
            })

            return item
          })
        }

        resolve(json)
      } catch (error) {
        reject(new Error('解析Excel文件失败'))
      }
    }

    reader.onerror = () => {
      reject(new Error('读取文件失败'))
    }

    reader.readAsBinaryString(file)
  })
}

// 验证数据
const validateData = (data: any[]) => {
  const result: any[] = []
  const errors: { row: number; field: string; value: any; message: string }[] =
    []

  data.forEach((item, index) => {
    const validationErrors: { field: string; value: any; message: string }[] =
      []

    // 验证每个字段
    Object.entries(props.validationRules).forEach(([field, rule]) => {
      const value = item[field]

      // 检查必填项
      if (value === undefined || value === null || value === '') {
        validationErrors.push({
          field,
          value,
          message: `${field}是必填项`,
        })
        return
      }

      // 检查正则匹配
      if (rule.pattern && !rule.pattern.test(String(value))) {
        validationErrors.push({
          field,
          value,
          message: rule.message || `${field}格式不正确`,
        })
      }
    })

    if (validationErrors.length > 0) {
      // 添加行号信息
      validationErrors.forEach((error) => {
        errors.push({
          row: index + 2, // +2 因为Excel从1开始，且有表头行
          ...error,
        })
      })
    } else {
      result.push(item)
    }
  })

  return { result, errors }
}
</script>

<style scoped></style>
